
package models.spider.actor;

import java.util.Date;

import models.spider.index.Entry;
import models.spider.index.Queue;
import models.spider.stats.Stopwatch;
import play.db.jpa.JPA;
import akka.actor.UntypedActor;
import akka.event.Logging;
import akka.event.LoggingAdapter;

public class Index extends UntypedActor {

    protected models.spider.index.Index index;
    protected Queue                     queue;
    protected LoggingAdapter            log = null;

    static class Message {

    }

    static class Add extends Message {

        protected String url = null;

        Add(final String url) {
            this.url = url;
        }

        public String getUrl() {
            return url;
        }
    }

    static class Refresh extends Message {

        protected String url = null;

        Refresh(final String url) {
            this.url = url;
        }

        public String getUrl() {
            return url;
        }
    }

    static class Success extends Message {

        protected String url = null;

        Success(final String url) {
            this.url = url;
        }

        public String getUrl() {
            return url;
        }

    }

    static class Failure extends Message {

        protected String url = null;

        Failure(final String url) {
            this.url = url;
        }

        public String getUrl() {
            return url;
        }
    }

    static class Next extends Message {

        protected String url = null;

        Next(final String url) {
            this.url = url;
        }

        Next() {
            this(null);
        }

        public String getUrl() {
            return url;
        }
    }

    Index(final models.spider.config.Factory config) {
        log = Logging.getLogger(getContext().system(), this);
        log.debug("index new");

        this.index = config.newIndex();
        this.queue = config.newQueue();
    }

    @Override
    public void onReceive(final Object message) throws Exception {
        if (message instanceof Add) {
            JPA.withTransaction(new play.libs.F.Callback0() {

                @Override
                public void invoke() throws Throwable {
                    add((Add) message);
                }
            });
        } else if (message instanceof Refresh) {
            JPA.withTransaction(new play.libs.F.Callback0() {

                @Override
                public void invoke() throws Throwable {
                    refresh((Refresh) message);
                }
            });
        } else if (message instanceof Success) {
            JPA.withTransaction(new play.libs.F.Callback0() {

                @Override
                public void invoke() throws Throwable {
                    success((Success) message);
                }
            });
        } else if (message instanceof Failure) {
            JPA.withTransaction(new play.libs.F.Callback0() {

                @Override
                public void invoke() throws Throwable {
                    failure((Failure) message);
                }

            });

        } else if (message instanceof Next) {
            JPA.withTransaction(new play.libs.F.Callback0() {

                @Override
                public void invoke() throws Throwable {
                    next((Next) message);
                }
            });
        } else {
            unhandled(message);
        }

        // log.debug("index onReceive done");
    }

    protected void add(final Add message) {
        // log.debug("index add");
        queue.add(message.url);
    }

    protected void refresh(final Refresh message) {
        // log.debug("index refresh");
        queue.refresh(message.url);
    }

    protected void success(final Success message) {
        Stopwatch watch = new Stopwatch("Index Succcess");
        index.success(message.url);
        log.debug(watch.stop().toString());
    }

    protected void failure(final Failure message) {
        // log.debug("index failure");
        index.failure(message.url);
    }

    protected void next(final Next message) {
        // log.debug("index next em id" + JPA.em().toString());
        Date start = new Date();
        // log.debug("index next start");
        Entry entry = queue.remove();
        if (entry == null) {
            log.debug("index next entry is null");
            return;
        }
        getSender().tell(new Next(entry.getUrl()), self());
        Date end = new Date();
        Long elapsed = (end.getTime() - start.getTime());
        log.debug("index next done elapsed = " + elapsed);
    }

    @Override
    public void preStart() {
        // log.debug("index pre start");
    }

    @Override
    public void postStop() {
        // log.debug("index post stop");
    }

}
